package secondary.employmentlaw;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import ontology.EmploymentLawOntology;
import ontology.UMCourtLOntology;
import ontology.UMCourtLVocabulary;
import ontology.actions.employmentlaw.GetUtilities;
import ontology.actions.employmentlaw.GetUtility;
import ontology.actions.general.ReturnUtilities;
import ontology.actions.general.ReturnUtility;
import ontology.concepts.employmentlaw.Outcome;
import classes.MessageTemplates;
import classes.UMCourtAgent;
import jade.content.Concept;
import jade.content.ContentElement;
import jade.content.lang.Codec;
import jade.content.lang.Codec.CodecException;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.content.onto.OntologyException;
import jade.content.onto.UngroundedException;
import jade.content.onto.basic.Action;
import jade.core.behaviours.CyclicBehaviour;
import jade.lang.acl.ACLMessage;
import jade.util.leap.ArrayList;

public class UtilityL extends UMCourtAgent implements UMCourtLVocabulary{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 464937464163563007L;
	private static Connection C;
	private static Statement Stmt;
	private final MessageTemplates mt = new MessageTemplates();
	private Codec codec = new SLCodec();
	private Ontology contology = EmploymentLawOntology.getInstance();
	//private Ontology negoOntology = NegotiationOntology.getInstance();
	long stime = 0;
	
	@Override
	protected void setup() 
	{
		System.out.println(getDate()+ ": "+this.getLocalName()+" agent is now running...");
		registerAgent((String)getArguments()[0]);
		
		// Register language and ontology
	    getContentManager().registerLanguage(codec);
	    getContentManager().registerOntology(contology);
	    //getContentManager().registerOntology(negoOntology);
		
		C = connectDB();
		
		this.addBehaviour(new receiveBehaviour());
	}
	
	
	
	//behaviours
	class receiveBehaviour extends CyclicBehaviour
	{
		@Override
		public void action() 
		{
			ACLMessage msg = receive();
	        if (msg == null) 
	        { 
	        	block(); 
	        	return; 
	        }
	        
	        
	        try 
			{
	        	ContentElement content = getContentManager().extractContent(msg);
		        Concept action = ((Action)content).getAction();
         		
		        switch (msg.getPerformative()) 
		        {
		        case (ACLMessage.REQUEST):
			        if (action instanceof GetUtilities)
			        {
			        	stime = System.currentTimeMillis();
			        	content = getContentManager().extractContent(msg);
			            GetUtilities gu = (GetUtilities)((Action)content).getAction();
			            ArrayList utilities = new ArrayList();
			            
			            ArrayList ids = gu.getIds(); //The ids of the cases to compute utility
			            ArrayList outcomes = new ArrayList();
			            //for each case, fetch info from database
			            for (int i=0;i<ids.size();i++)
			            {
			            	Statement select = C.createStatement();
		            		ResultSet result = select.executeQuery("SELECT daysReceived, nightWork, suplementaryWork FROM umCourtl.outcomes WHERE idoutcomes = '"+ids.get(i)+"'");
		            		
		            		while (result.next())
		            		{
		            			Float daysReceived = result.getFloat(1);
		            			Float nightWork = result.getFloat(2);
		            			Float supplementaryWork = result.getFloat(3);
		            			
		            			Outcome outcome = new Outcome();
		            			outcome.setDaysReceived(daysReceived.intValue());
		            			outcome.setNightWork(nightWork);
		            			outcome.setSuplementaryWork(supplementaryWork);
		            			outcome.setID((String) ids.get(i));
		            			outcomes.add(outcome);
		            			
		            			//antiquity
		            			Float utility = daysReceived * gu.getDayWage() * gu.getAntiquity();
		            			
		            			//night work = percentage of night work paid * total hours of night work * salary per hour * 2
		            			utility += nightWork * gu.getNightWork() * gu.getHourWage() * 2; //night work is paid double
		            			
		            			//supplementary work = percentage of supplementary work paid * total hours of supplementary work * salary per hour * 2
		            			utility += supplementaryWork * gu.getSupplementaryWork() * gu.getHourWage() * 2; //night work is paid double
		            			
		            			utilities.add(utility);
		            		}
			            }
			            
			            ReturnUtilities ru = new ReturnUtilities();
			            ru.setIds(ids);
			            ru.setUtilities(utilities);
			            ru.setOutcomes(outcomes);
			            
			            //Send the result to the agent that originally requested it
			            ACLMessage m = new ACLMessage(ACLMessage.INFORM);
			            m.setConversationId(msg.getConversationId());
			            m.setLanguage(codec.getName());
						m.setOntology(contology.getName());
			            getContentManager().fillContent(m, new Action(msg.getSender(), ru));
			            m.addReceiver(msg.getSender());
			            myprintln("Sending results from Utility request to "+msg.getSender());
			            sendNewTime("ut", stime);
						send(m);
		        	}
		        
		        	if (action instanceof GetUtility)
			        {
		        		stime = System.currentTimeMillis();
			        	myprintln("Received Compute Utility request from "+msg.getSender());
			        	content = getContentManager().extractContent(msg);
			            GetUtility gu = (GetUtility)((Action)content).getAction();
			            
			            Outcome out = gu.getOutcome();
			            Integer daysReceived = out.getDaysReceived();
            			Float nightWork = out.getNightWork();
            			Float supplementaryWork = out.getSuplementaryWork();
            			
            			
            			//antiquity
            			Float utility = daysReceived * gu.getDayWage() * gu.getAntiquity();
            			
            			//night work = percentage of night work paid * total hours of night work * salary per hour * 2
            			utility += nightWork * nightWork * gu.getHourWage() * 2; //night work is paid double
            			
            			//supplementary work = percentage of supplementary work paid * total hours of supplementary work * salary per hour * 2
            			utility += supplementaryWork * supplementaryWork * gu.getHourWage() * 2; //night work is paid double
			            
            			ReturnUtility ru = new ReturnUtility();
            			ru.setUtility(utility);
            			//Send the result to the agent that originally requested it
			            ACLMessage m = new ACLMessage(ACLMessage.INFORM);
			            m.setConversationId(msg.getConversationId());
			            m.setLanguage(codec.getName());
						m.setOntology(contology.getName());
			            getContentManager().fillContent(m, new Action(msg.getSender(), ru));
			            m.addReceiver(msg.getSender());
			            m.setConversationId(msg.getConversationId());
			            myprintln("Sending results from Utility request to "+msg.getSender());
			            sendNewTime("ut", stime);
						send(m);
			        }
		        }	
			}
	        catch (SQLException e) {e.printStackTrace();}
			catch (UngroundedException e) {e.printStackTrace();} 
			catch (CodecException e) {e.printStackTrace();} 
			catch (OntologyException e) {e.printStackTrace();}
			
			
			
			
		}
	}
	
}
